<template>
    <div class="konva-container" :style="containerStyle">
        <div class="bg-mask"></div>
        <div class="konva-el" ref="containerRef"></div>
        <el-image
            class="search-plus"
            :src="searchPlusIcon"
            @click="showImage"
        ></el-image>
        <div class="image-box">
            <!-- <img :src="dataURL" /> -->
            <el-image
                ref="elImage"
                style="width: 100px; height: 100px"
                :src="dataURL"
                :preview-src-list="[dataURL]"
                @load="onImageLoad"
            >
            </el-image>
        </div>
    </div>
</template>
<script>
import {
    addFieldsToMarksArr,
    getImageAdaptSize,
    handleMarkFields,
    loadImage,
} from "./utils";
import EssayEvaluator from "./EssayEvaluator";
import { cloneDeep, debounce } from "lodash";
import searchPlusIcon from "../../assets/paperTrace/search-plus.png";

export default {
    props: {
        markData: {
            type: Array,
            default: () => [],
        },
        config: {
            type: Object,
            default: () => ({
                stageWidth: 800,
                stageHeight: 600,
                viewType: "comprehensive",
                score: 0,
                subject: "chinese",
                flunked: true,
                dir: "horizontal",
            }),
        },
    },
    inject: ["markSelInfo"],
    data() {
        return {
            essayInstance: null,
            essayImageList: [],
            groupSize: 0,
            wordList: [],
            sentenceList: [],
            paragraphList: [],
            correctionList: [],
            isSelfTrigger: false,
            searchPlusIcon,
            dataURL: "",
            imgLoaded: false,
        };
    },
    computed: {
        containerStyle() {
            return {
                width: `${this.config.stageWidth}px`,
                height: `${this.config.stageHeight}px`,
            };
        },
        isVertical() {
            return this.config.dir === "vertical";
        },
        markSelComputedInfo() {
            return [
                this.markSelInfo.markSelType,
                this.markSelInfo.markSelIndex,
            ];
        },
        markListComputed() {
            return [
                this.wordList,
                this.sentenceList,
                this.paragraphList,
                this.correctionList,
            ];
        },
    },
    watch: {
        markData: {
            handler() {
                this.handleMarkData();
            },
            deep: true,
        },
        "config.viewType"(newViewType, oldViewType) {
            this.debounceChangeMarks(newViewType, oldViewType);
        },
        markListComputed() {
            this.debounceChangeMarks(this.config.viewType);
        },
        markSelComputedInfo: {
            handler([type, indexMap]) {
                // 只有非自身触发才执行
                if (!this.isSelfTrigger) {
                    this.handleHighlight(type, indexMap);
                } else {
                    this.isSelfTrigger = false;
                }
            },
            deep: true,
        },
        groupSize(size) {
            if (this.config.stageWidth > size) {
                this.$refs.containerRef.classList.add("center");
            }
        },
    },
    async mounted() {
        await this.handleEssayImages(); // 处理图片信息
        this.calculateGroupSize();
        this.init();
        this.debounceChangeMarks = debounce(this.changeMarks.bind(this), 200);
    },
    methods: {
        async handleEssayImages() {
            const { dir, stageWidth, stageHeight } = this.config;
            const urls = this.markData.map((item) => item.url);
            const imgs = [];
            for (let i = 0; i < urls.length; i++) {
                const img = await loadImage(urls[i]);
                const { width, height } = await getImageAdaptSize(img, {
                    dir,
                    stageWidth,
                    stageHeight,
                });
                const x = this.isVertical
                    ? 0
                    : i === 0
                    ? 0
                    : imgs[i - 1].width + imgs[i - 1].x;
                const y = this.isVertical
                    ? i === 0
                        ? 0
                        : imgs[i - 1].height + imgs[i - 1].y
                    : 0;
                const adaptScale = this.isVertical
                    ? stageWidth / img.width
                    : stageHeight / img.height;

                this.markData[i].adaptScale = adaptScale;
                imgs.push({
                    img,
                    x,
                    y,
                    width,
                    height,
                });
            }
            this.essayImageList = imgs;
        },
        handleMarkData() {
            if (this.essayImageList.length === 0) return;

            let wordArr = [],
                sentencesArr = [],
                paragraphArr = [],
                correctionArr = [];

            for (let i = 0; i < this.markData.length; i++) {
                const { selections = {}, adaptScale = 1 } = this.markData[i];
                // 此处改为深拷贝，防止多触发一次上面的watch
                const words = cloneDeep(selections.words || []);
                const sentences = cloneDeep(selections.sentences || []);
                const paragraphs = cloneDeep(selections.paragraphs || []);
                const corrections = cloneDeep(selections.corrections || []);

                // 添加paperIndex到marks中
                addFieldsToMarksArr(
                    [words, sentences, paragraphs, corrections],
                    {
                        paperIndex: i, // 试卷索引
                    }
                );
                // 处理坐标
                this.handleMarksCooridates(words, adaptScale);
                this.handleMarksCooridates(sentences, adaptScale);
                this.handleMarksCooridates(paragraphs, adaptScale);
                this.handleMarksCooridates(corrections, adaptScale);
                // 添加到列表中
                wordArr = [...wordArr, ...words];
                sentencesArr = [...sentencesArr, ...sentences];
                paragraphArr = [...paragraphArr, ...paragraphs];
                correctionArr = [...correctionArr, ...corrections];
            }
            // 添加索引和isHighlight字段
            handleMarkFields(
                wordArr,
                sentencesArr,
                paragraphArr,
                correctionArr
            );

            this.wordList = wordArr;
            this.sentenceList = sentencesArr;
            this.paragraphList = paragraphArr;
            this.correctionList = correctionArr;
        },
        handleMarksCooridates(marks, adaptScale) {
            marks.forEach((mark, index) => {
                const { paperIndex } = mark;
                const cooridates = mark.cooridates;
                cooridates.forEach((cooridate) => {
                    const x1 = (cooridate.x1 = cooridate.x1 * adaptScale);
                    const y1 = (cooridate.y1 = cooridate.y1 * adaptScale);
                    const x2 = (cooridate.x2 = cooridate.x2 * adaptScale);
                    const y2 = (cooridate.y2 = cooridate.y2 * adaptScale);
                    const { x: imageX, y: imageY } =
                        this.essayImageList[paperIndex];
                    cooridate.x = this.isVertical ? x1 : x1 + imageX;
                    cooridate.y = this.isVertical ? y1 + imageY : y1;
                    cooridate.width = x2 - x1;
                    cooridate.height = y2 - y1;
                });
            });
        },
        init() {
            const isVertical = this.isVertical;
            const { stageWidth, stageHeight, score } = this.config;
            // 初始化图层和组
            const groupConfig = {
                width: isVertical ? stageWidth : this.groupSize,
                height: isVertical ? this.groupSize : stageHeight,
            };
            const essay = new EssayEvaluator({
                onMarkClick: this.onMarkClick.bind(this),
            });
            // 初始化stage
            essay.initStage({
                container: this.$refs.containerRef,
                width:
                    stageWidth > this.groupSize ? this.groupSize : stageWidth,
                height: stageHeight,
            });
            essay.initLayer(groupConfig);
            essay.renderBgImages(this.essayImageList); // 渲染背景图
            essay.renderMask(); //渲染半透明遮罩
            essay.initMarkGroup(); // 渲染分数
            essay.renderScore(score); // 渲染分数
            essay.bindDragAndScaleEvent();
            this.essayInstance = essay;
        },
        calculateGroupSize() {
            let size = 0;
            for (let i = 0; i < this.essayImageList.length; i++) {
                const { width, height } = this.essayImageList[i];
                size += this.isVertical ? height : width;
            }
            this.groupSize = size;
        },
        changeMarks(newViewType, oldViewType) {
            const essayIns = this.essayInstance;

            essayIns.clearAllOrderNumber();
            // 综合点评切换到字词句点评特殊时不处理
            if (
                newViewType === "wordsentence" &&
                oldViewType === "comprehensive" &&
                (this.wordList.length > 0 || this.sentenceList.length > 0)
            ) {
                //
            } else {
                essayIns.clearAllMark();
                this.clearHighlight(oldViewType);
            }

            if (newViewType === "comprehensive") {
                if (this.subject === "english") {
                    this.renderCorrectionMarks(false);
                } else {
                    this.renderWordsentenceMarks(false);
                }
            } else if (newViewType === "paragraph") {
                this.renderParagraphMarks();
            } else if (newViewType === "wordsentence") {
                this.renderWordsentenceMarks();
            } else if (newViewType === "correction") {
                this.renderCorrectionMarks();
            }
            this.isSelfTrigger = false;
        },
        clearHighlight(viewType) {
            if (viewType === "paragraph") {
                this.paragraphList.forEach(
                    (item) => (item.isHighlight = false)
                );
            } else if (viewType === "wordsentence") {
                this.wordList.forEach((item) => (item.isHighlight = false));
                this.sentenceList.forEach((item) => (item.isHighlight = false));
            } else if (viewType === "correction") {
                this.correctionList.forEach(
                    (item) => (item.isHighlight = false)
                );
            }
        },
        hasHighlight(list) {
            return list.some((item) => item.isHighlight);
        },
        highlightMark(type, index) {
            this.essayInstance.highlightMark(type, index);
        },
        onMarkClick(type, index) {
            this.$emit(`markClick`, type, index);
            this.isSelfTrigger = true;
            this.markSelInfo.changeMarkSelIndex(type, index);
        },
        renderWordsentenceMarks(showOrder = true) {
            const essayIns = this.essayInstance;
            if (this.wordList.length > 0) {
                essayIns?.renderWords(this.wordList);
                essayIns?.bindMarkEvent("word");
            }
            if (this.sentenceList.length > 0) {
                essayIns?.renderSentences(this.sentenceList);
                essayIns?.bindMarkEvent("sentence");
                showOrder && essayIns?.renderOrderNumber("sentence");
            }
        },
        renderParagraphMarks() {
            const essayIns = this.essayInstance;
            if (this.paragraphList.length > 0) {
                essayIns?.renderParagraphs(this.paragraphList);
                essayIns?.renderOrderNumber("paragraph");
                essayIns?.bindMarkEvent("paragraph");
                if (!this.hasHighlight(this.paragraphList)) {
                    this.highlightMark("paragraph", 1);
                }
            }
        },
        renderCorrectionMarks(showOrder = true) {
            const essayIns = this.essayInstance;
            if (this.correctionList.length > 0) {
                essayIns?.renderCorrections(this.correctionList);
                showOrder && essayIns?.renderOrderNumber("correction");
                essayIns?.bindMarkEvent("correction");
                if (!this.hasHighlight(this.correctionList)) {
                    this.highlightMark("correction", 1);
                }
            }
        },
        handleHighlight(type, selIndexMap) {
            if (type === "word" || type === "sentence") {
                this.essayInstance?.cancelMarkHighlight("word");
                this.essayInstance?.cancelMarkHighlight("sentence");
            }
            this.highlightMark(type, selIndexMap[`${type}Index`]);
        },
        toDataURL() {
            const url = this.essayInstance?.toDataURL();
            return url;
        },
        showImage() {
            const url = this.toDataURL();

            if (this.dataURL !== url) {
                this.imgLoaded = false;
                this.dataURL = url;
            } else {
                this.onImageLoad();
            }
        },
        onImageLoad() {
            if (!this.imgLoaded) {
                this.imgLoaded = true;
            }
            this.$refs.elImage.$el.querySelector("img").click();
        },
    },
    unmounted() {
        this.essayInstance.unBindDragAndScaleEvent();
        this.essayInstance.unBindMarkEvent(
            "word",
            "sentence",
            "paragraph",
            "correction"
        );
    },
};
</script>
<style>
.konva-container {
    position: relative;
    background-color: #fff;
}
.bg-mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.2);
}
.konva-el.center div {
    margin: 0 auto;
}
.konva-container .search-plus {
    position: absolute;
    bottom: 20px;
    right: 20px;
    width: 50px;
    height: 50px;
    cursor: pointer;
}
.image-box {
    position: absolute;
    top: 0;
    right: 9999px;
}
</style>
